package edu.hda.pt.server.connections;

import java.io.IOException;
import java.net.UnknownHostException;

import org.xsocket.connection.INonBlockingConnection;
import org.xsocket.connection.IServer;
import org.xsocket.connection.Server;
import org.xsocket.connection.IConnection.FlushMode;

import edu.hda.pt.server.PTServer;
import edu.hda.pt.server.connections.xsocket.ServerHandler;
import edu.hda.pt.server.connections.xsocket.StreamThread;
import edu.hda.pt.utils.Stream;
import edu.hda.pt.utils.Stream.StreamState;
import edu.hda.pt.utils.connections.xsocket.XSocketConstants;

/**
 * Server implementation for the connection method xSocket
 * 
 * @author Marc Hammerton
 * 
 */
public class PTServerXSocket extends PTServer {

	private IServer server;
	private StreamThread st;

	/**
	 * @see edu.hda.pt.server.PTServer#start()
	 */
	@Override
	public void start() {
		try {

			System.setProperty("org.xsocket.connection.server.workerpoolSize",
					"" + 1);

			server = new Server(XSocketConstants.PORT, new ServerHandler(this));
			server.setFlushMode(FlushMode.ASYNC);
			server.start();

			st = new StreamThread();
			st.start();
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * @see edu.hda.pt.server.PTServer#stop()
	 */
	@Override
	public void stop() {
		try {
			server.close();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	/**
	 * Method for handling stream requests. If a new stream request is received,
	 * it is added to the
	 * {@link edu.hda.pt.server.connections.xsocket.StreamThread}, which then
	 * starts sending frames to the client. When a client requests the stream to
	 * be stopped, the client is removed from the
	 * {@link edu.hda.pt.server.connections.xsocket.StreamThread}
	 * 
	 * @param stream
	 *            - The stream object with information about the request
	 * @param connection
	 *            - The connection with information about the client connection
	 * @return The stream object containing the information about the stream
	 *         state
	 */
	public Stream handleStream(Stream stream, INonBlockingConnection connection) {

		if (stream.getState() == StreamState.START) {
			System.out.println("Starting stream");
			// Init StreamThread
			if (st.getFileSize() == 0) {
				synchronized (st) {
					st.setFileSize(stream.getFs());
					st.addConnection(connection);
					st.notify();
				}

			} else if (stream.getFs() == st.getFileSize()) {
				synchronized (st) {
					st.addConnection(connection);
				}
			}
			stream.setState(StreamState.RUNNING);

		} else if (stream.getState() == StreamState.FINISH) {
			st.removeConnection(connection);
			System.out.println(connection + ": streaming stopped");
			stream.setState(StreamState.STOPPED);
		}

		return stream;
	}

}
